Skip to content

fix: Cache middleware only caches static assets, not HTML pages#8

Merged
Starry-Sky-World merged 1 commit into
mainfrom
feat/langfuse-trace-notice
May 22, 2026
Merged

fix: Cache middleware only caches static assets, not HTML pages#8
Starry-Sky-World merged 1 commit into
mainfrom
feat/langfuse-trace-notice

Conversation

@Starry-Sky-World
Copy link
Copy Markdown

@Starry-Sky-World Starry-Sky-World commented May 22, 2026

Problem

The Cache middleware was setting max-age=604800 (cache for one week) on ALL non-root responses, including HTML pages and 302 redirects.

Chrome has a special in-memory cache for 302 redirect mappings that is NOT controlled by DevTools "Disable cache". When the system theme changed or different server instances had different themes, cached redirects in opposite directions created an infinite loop:

/dashboard → 302 → /console → 302 → /dashboard → ... → ERR_TOO_MANY_REDIRECTS

Fix

Only set max-age=604800 for static assets (JS, CSS, fonts, images, etc.). HTML pages and other routes get no-cache to prevent stale redirects from being cached.

This complements PR #7 which removed the server-side path redirect entirely.

Summary by CodeRabbit

  • Refactor
    • Updated caching strategy: static assets (JavaScript, CSS, fonts, images, icons) now cache for one week, reducing unnecessary downloads. Dynamic content and the homepage use a no-cache policy to ensure timely updates.

Review Change Stack

The Cache middleware was setting max-age=604800 on ALL non-root responses,
including HTML pages and 302 redirects. This caused Chrome to cache 302
redirect mappings persistently (this cache is NOT controlled by DevTools
'Disable cache'). When the system theme changed or different server
instances had different themes, cached redirects in opposite directions
created an infinite loop.

Fix: Only set max-age=604800 for static assets (JS, CSS, fonts, images).
HTML pages and other routes get no-cache to prevent stale redirects.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ef18c10-4997-401a-b2c2-a5ffee709e09

📥 Commits

Reviewing files that changed from the base of the PR and between b10a188 and 588cc83.

📒 Files selected for processing (1)
  • middleware/cache.go

📝 Walkthrough

Walkthrough

The Cache() Gin middleware is refactored to classify HTTP requests by URL path and apply differentiated cache policies: static assets (JS, CSS, fonts, images, icons, maps, manifests) receive one-week caching, while dynamic routes and / receive no-cache headers. A new isStaticAsset() helper function determines classification by file extension.

Changes

Cache control refactoring

Layer / File(s) Summary
Static asset-aware cache control
middleware/cache.go
Import strings package; refactor Cache() middleware to extract c.Request.URL.Path, classify it with new isStaticAsset() helper, and set Cache-Control to max-age=604800 for static assets or no-cache for dynamic content. isStaticAsset() returns false for / and true when path ends with static file extensions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hop through assets, swift and fleet,
Cache them long, a static treat,
Dynamic routes need fresh air clear,
No-cache headers, crisp and dear!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/langfuse-trace-notice

Comment @coderabbitai help to get the list of available commands and usage tips.

@Starry-Sky-World Starry-Sky-World merged commit 7a9aad7 into main May 22, 2026
3 of 4 checks passed
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Cache middleware to target static assets for long-term caching using a new isStaticAsset helper function. The reviewer recommended optimizing this function by using a switch statement for better performance and converting extensions to lowercase to ensure case-insensitive matching.

Comment thread middleware/cache.go
Comment on lines +22 to +34
func isStaticAsset(path string) bool {
if path == "/" {
return false
}
staticExtensions := []string{".js", ".css", ".woff", ".woff2", ".ttf", ".eot",
".svg", ".png", ".jpg", ".jpeg", ".gif", ".ico", ".webp", ".map", ".webmanifest"}
for _, ext := range staticExtensions {
if strings.HasSuffix(path, ext) {
return true
}
}
return false
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation of isStaticAsset performs a linear search through a slice on every request, which is inefficient ($O(N)$). Additionally, it is case-sensitive, meaning extensions like .JS or .CSS will not be recognized as static assets, leading to suboptimal caching for those files.

Using a switch statement on the file extension is more idiomatic in Go, provides better performance, and allows for easy case-insensitive matching.

func isStaticAsset(path string) bool {
	dot := strings.LastIndexByte(path, '.')
	if dot == -1 {
		return false
	}
	ext := strings.ToLower(path[dot:])
	switch ext {
	case ".js", ".css", ".woff", ".woff2", ".ttf", ".eot", ".svg", ".png", ".jpg", ".jpeg", ".gif", ".ico", ".webp", ".map", ".webmanifest":
		return true
	}
	return false
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant